Process
	.getModuleByName({ linux: 'libc.so', darwin: 'libSystem.B.dylib', windows: 'ws2_32.dll' }[Process.platform])
	.enumerateExports().filter(x => x.type === 'function' && ['recv', 'send', 'read', 'write', 'WSARecv', 'WSASend'].some(y => x.name === y))
	.forEach(x => {
		Interceptor.attach(x.address, {
			onEnter: function (args) {
				// int recv([in] SOCKET s, [out] char *buf, [in] int len, [in] int flags);
				// int send([in] SOCKET s, [in] const char *buf, [in] int len, [in] int flags);
				// ssize_t read(int fd, void buf[.count], size_t count);
				// ssize_t write(int fd, const void buf[.count], size_t count);
				// int WSARecv([in] SOCKET s, [in, out] LPWSABUF lpBuffers, [in] DWORD dwBufferCount, [out] LPDWORD lpNumberOfBytesRecvd, [in, out] LPDWORD lpFlags, [in] LPWSAOVERLAPPED lpOverlapped, [in] LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
				// int WSASend([in] SOCKET s, [in] LPWSABUF lpBuffers, [in] DWORD dwBufferCount, [out] LPDWORD lpNumberOfBytesSent, [in] DWORD dwFlags, [in] LPWSAOVERLAPPED lpOverlapped, [in] LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);

				// console.log('attached');
				const fd = args[0].toInt32();
				const socktype = Socket.type(fd);
				if (socktype !== 'tcp' && socktype !== 'tcp6') {
					return;
				}

				const local_address = Socket.localAddress(fd);
				if (local_address === null) {
					return;
				}

				const remote_address = Socket.peerAddress(fd);
				if (remote_address === null) {
					return;
				}

				this._fd = fd;
				this._buf = ptr(args[1]);
				this._local_address = local_address.ip + ':' + local_address.port;
				this._remote_address = remote_address.ip + ':' + remote_address.port;
			},
			onLeave: function (retval) {
				// console.log('dettached');
				if (!this._fd) {
					return;
				}

				retval = retval.toInt32();
				if (retval > 0) {
					console.log(
						'function =', x.name, ',',
						'fd =', this._fd, ',',
						'local_address =', this._local_address, ',',
						'remote_address =', this._remote_address, ',',
						'buf_len =', retval, ',',
						'buf:\n', this._buf.readByteArray(retval),
						'\n', '*'.repeat(100));
				}
			}
		})
	});